package com.engine.jucailinkq.attendance.attendanceanalysis.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.engine.jucailinkq.attendance.attendanceanalysis.dto.clockpoint.ClockPointDTO;
import com.engine.jucailinkq.attendance.attendanceanalysis.service.ShiftService;
import com.engine.jucailinkq.attendance.attendanceanalysis.service.UtilService;
import com.engine.jucailinkq.attendance.attendanceanalysis.wrapper.UpdateAttendanceResultWrapper;
import com.engine.jucailinkq.attendance.attendanceplan.service.AttendancePlanService;
import com.engine.jucailinkq.attendance.attendanceplan.service.impl.AttendancePlanServiceImpl;
import com.engine.jucailinkq.attendance.enums.CheckBoxEnum;
import com.engine.jucailinkq.attendance.enums.ClassBelongToEnum;
import com.engine.jucailinkq.attendance.enums.ClassSegmentTypeEnum;
import com.engine.jucailinkq.attendance.enums.ClockPointEnum;
import com.engine.jucailinkq.common.util.DateUtil;
import com.engine.jucailinkq.common.util.DbTools;
import com.engine.common.util.ServiceUtil;
import com.engine.jucailinkq.common.util.ExtensionClassHolder;
import com.engine.jucailinkq.common.util.Utils;
import com.engine.core.impl.Service;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.icbc.api.internal.apache.http.E;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.Util;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: sy
 * @Description: 班次相关功能实现类
 * @Date: 2024/5/11
 **/
@Slf4j
public class ShiftServiceImpl extends Service implements ShiftService {
    private AttendancePlanService basicsetService = ServiceUtil.getService(AttendancePlanServiceImpl.class);
    private UtilService utilService = ServiceUtil.getService(UtilServiceImpl.class);
    private UpdateAttendanceResultWrapper updateAttendanceResultWrapper = ServiceUtil.getService(UpdateAttendanceResultWrapper.class);
    /**
     * 打卡匹配班次，返回班次id
     * @param empId 打卡人员id
     * @param pbData 排班结果
     * @param clockInData 需要包含分析日期以及分析日期前后2天的3天原始打卡数据
     * @return
     */
    @Override
    public Map<String, Object> punchMatchShift(String empId, Map<String,Object> pbData, List<Map<String, Object>> clockInData,Map<String,Map<String,Object>> clockInTimeMap) {
        //查询排班结果
//        String pbSql = "select * from uf_pbjg where id = " + schedulingResultId;
//        Map<String, Object> pbData = DbTools.getSqlToMap(pbSql);
        String shiftTeamId = Util.null2String(pbData.get("hxbz")).split("-")[0];
        String punchDate = Util.null2String(pbData.get("bcrq"));

        BaseBean baseBean = new BaseBean();
        RecordSet rs = new RecordSet();
        Map<String, Object> result = null;
        Map<String, Object> maxPriorityResult = null;
        if (!shiftTeamId.equals("")) {
            //候选班次
            String bcSql = "select * from uf_jcl_kq_hxbz_dt1 where mainid = " + shiftTeamId;
            List<Map<String, Object>> bcData = DbTools.getSqlToList(bcSql);
            if (bcData.size() > 0) {
                List<Map<String, Object>> waitCompareResultList = new ArrayList<>();
                //循环匹配，输出匹配结果
                for (Map<String, Object> bcMap : bcData) {
                    //获取班次要求打卡数据和请假、出差、加班数据处理后的卡点数据
                    Map<String, Object> waitCompareMap = dealClockInData(empId, pbData, clockInData, bcMap.get("bcxx").toString(), clockInTimeMap);
                    waitCompareMap.put("priorityValue", Util.null2String(bcMap.get("yxj")));
                    waitCompareResultList.add(waitCompareMap);
                }

                String startSign = punchDate + " 20:00";
                String endSign = DateUtil.AfterDay(punchDate, 1) + " 03:00";
                //比较匹配结果
                for (Map<String, Object> compareMap : waitCompareResultList) {
                    //分析每组数据，生成对应的ABCDE
                    compareMap = countMatchItem(compareMap);
                    String compareB = Util.null2String(compareMap.get("judgePartB"));
                    if (compareB.equals("")) {
                        continue;
                    }
                    // 如果要匹配夜班，则必须在当日20点到次日3点之间存在打卡
                    rs.execute("select sfkt from uf_jcl_kq_bcxx where id =" + compareMap.get("bcId"));
                    if (rs.next()) {
                        String sfktTemp = rs.getString("sfkt");
                        if (StringUtils.isNotEmpty(sfktTemp) && sfktTemp.equals("1")) {
                            int index = 0;
                            if (CollectionUtils.isEmpty(clockInData)) {
                                continue;
                            }
                            for (Map<String, Object> clockTempMap : clockInData) {
                                String signTemp = clockTempMap.get("signdate") + " " + clockTempMap.get("signtime");
                                if (DateUtil.getTime(signTemp).compareTo(DateUtil.getTime(startSign)) >= 0 && DateUtil.getTime(endSign).compareTo(DateUtil.getTime(signTemp)) >= 0) {
                                    index = index + 1;
                                }
                            }
                            if (index == 0) {
                                continue;
                            }
                        }
                    }
                    if (result == null) {
                        result = compareMap;
                        continue;
                    }
                    //1-比较各候选班次实际打卡正常的时间点个数B
                    String resultB = Util.null2String(result.get("judgePartB"));
                    if (resultB.compareTo(compareB) != 0) {
                        result = resultB.compareTo(compareB) < 0 ? compareMap : result;
                        continue;
                    }
                    //2-B相同时,比较B/A最大。各候选班次（结合了请假、出差、加班等）需要打卡的时间点个数A
                    String resultA = Util.null2String(result.get("judgePartA"));
                    String compareA = Util.null2String(compareMap.get("judgePartA"));
                    double resultBDividedA = (resultA.equals("") || resultA.equals("0")) ? 999 : Double.parseDouble(resultB) / Double.parseDouble(resultA);
                    double compareBDividedA = (compareA.equals("") || compareA.equals("0")) ? 999 : Double.parseDouble(compareB) / Double.parseDouble(compareA);
                    if (resultBDividedA != compareBDividedA) {
                        result = resultBDividedA < compareBDividedA ? compareMap : result;
                        continue;
                    }
                    //3-B/A相同时C最小。异常总分钟数C
                    String resultC = Util.null2String(result.get("judgePartC"));
                    String compareC = Util.null2String(compareMap.get("judgePartC"));
                    if (resultC.compareTo(compareC) != 0) {
                        result = resultC.compareTo(compareC) > 0 ? compareMap : result;
                        continue;
                    }
                    //4-C相同时D最小,冗余总分钟数D
                    String resultD = Util.null2String(result.get("judgePartD"));
                    String compareD = Util.null2String(compareMap.get("judgePartD"));
                    if (resultD.compareTo(compareD) != 0) {
                        result = resultD.compareTo(compareD) > 0 ? compareMap : result;
                        continue;
                    }
                    //5-D相同时E最小,班次优先级E（候选班组上有各班次的优先级设置）
                    String resultE = Util.null2String(result.get("judgePartE"));
                    String compareE = Util.null2String(compareMap.get("judgePartE"));
                    if (resultE.compareTo(compareE) != 0) {
                        result = resultE.compareTo(compareE) > 0 ? compareMap : result;
                    }
                }

                if (CollectionUtils.isEmpty(result)) {
                    baseBean.writeLog("punchMatchShift result is null.");
                } else {
                    baseBean.writeLog("punchMatchShift result is:" + JSONObject.toJSONString(result));
                }

                //全天没有打卡时,看上一个工作日的班次为优先，如果前一个工作日也没有班次，按优先级
                if (result == null) {
                    //获取上一个工作日的班次
                    String lastWorkDayInfoSql = "select * from uf_jcl_kq_cqjg where rqlx = 0 and ygid = " + empId + " and rq < '" + punchDate + "' order by rq desc limit 1;";
                    Map<String, Object> lastWorkDayInfo = DbTools.getSqlToMap(lastWorkDayInfoSql);

                    if (CollectionUtils.isEmpty(lastWorkDayInfo)) {
                        baseBean.writeLog("punchMatchShift lastWorkDayInfo is null.");
                    } else {
                        baseBean.writeLog("punchMatchShift lastWorkDayInfo is:" + JSONObject.toJSONString(lastWorkDayInfo));
                    }

                    String bcId = Util.null2String(lastWorkDayInfo.get("bc"));
                    List<Map<String, Object>> bcInfo = waitCompareResultList.stream().filter(f -> f.get("bcId").toString().equals(bcId)).collect(Collectors.toList());
                    if (!bcId.equals("") && bcInfo.size() > 0) {
                        result = bcInfo.get(0);
                    } else {
                        //上一个工作日没有班次时
                        maxPriorityResult = waitCompareResultList.stream().min(Comparator.comparing(e -> new Integer(String.valueOf(e.get("judgePartE"))))).get();
                        result = maxPriorityResult;
                    }
                }
            }

        }

        return result;
    }

    /**
     * 计算卡点数据的匹配条件元素的具体数值
     * 考量元素有：
     * 各候选班次（结合了请假、出差、加班等）需要打卡的时间点个数A；
     * 各候选班次实际打卡正常的时间点个数B；
     * 异常总分钟数C；
     * 冗余总分钟数D；
     * 班次优先级E（候选班组上有各班次的优先级设置）
     * @param compareMap 班次匹配卡点数据
     * @return
     */
    private Map<String, Object> countMatchItem(Map<String, Object> compareMap) {
        List<ClockPointDTO> clockInTimeData = (List<ClockPointDTO>) compareMap.get("clockInTimeData");
        int requireClockInNum = clockInTimeData == null ? 0 : clockInTimeData.size();
        int rightClockInNum = 0;
        int abnormalMinutes = 0;
        int redundantMinutes = 0;
        if (clockInTimeData == null || clockInTimeData.size() == 0) {
            compareMap.put("judgePartA", String.valueOf(requireClockInNum));
            compareMap.put("judgePartB", String.valueOf(rightClockInNum));
            compareMap.put("judgePartC", String.valueOf(abnormalMinutes));
            compareMap.put("judgePartD", String.valueOf(redundantMinutes));
            compareMap.put("judgePartE", compareMap.get("priorityValue"));
            return compareMap;
        }
        //班次要求打卡时间，时间格式2023-11-12 09:15
        String classTime = "";
        //弹性要求打卡时间，时间格式2023-11-12 09:15
        String elasticTime = "";
        String compareTime = "";
        //实际打卡数据。格式为
        // {2023-11-12 09:00|0|3|2023-11-12 09:15 ={signtime=09:11:00, id=48, userid=53, signdate=2023-11-12}}
        // 班次时间|打卡类型（上班卡或下班卡）|打卡时间处所在位置timeType|弹性时间 = 打卡时间map集合
        Map<String, Object> clockTimeMap = new HashMap<>();
        //实际打卡时间
        String clockTime = "";
        ClockPointEnum pointType;
        ClockPointEnum timeType;
        for (ClockPointDTO dto : clockInTimeData) {
            pointType = dto.getPointType();
            timeType = dto.getTimeType();
            clockTimeMap = dto.getClockTime();
            clockTime = (clockTimeMap != null ? Util.null2String(clockTimeMap.get("signdate")) : "")
                    + " "
                    + (clockTimeMap != null ? Util.null2String(clockTimeMap.get("signtime")) : "");
            classTime = dto.getClassTime();
            elasticTime = dto.getElasticTime();
            compareTime = Util.null2String(elasticTime).equals("") ? classTime : elasticTime;
            //判断这个需要打卡的时间点，有没有正常打卡
            if (ClockPointEnum.EMPTY.equals(timeType) || clockTimeMap == null || clockTime.length() < 16) {
                continue;
            } else if (ClockPointEnum.START.equals(pointType) && ClockPointEnum.AFTER.equals(timeType)) {
                //迟到，异常打卡-记录异常分钟数
                int betweenTime = DateUtil.getBetWeenMinutes(compareTime, clockTime.substring(0, 16));
                abnormalMinutes = abnormalMinutes + betweenTime;
            } else if (ClockPointEnum.START.equals(pointType) && ClockPointEnum.BEFORE.equals(timeType)) {
                //早到，正常打卡-记录冗余分钟数、打卡正常的时间点个数
                rightClockInNum++;
                int betweenTime = DateUtil.getBetWeenMinutes(clockTime.substring(0, 16), compareTime);
                redundantMinutes = redundantMinutes + betweenTime;
            } else if (ClockPointEnum.END.equals(pointType) && ClockPointEnum.BEFORE.equals(timeType)) {
                //早退，异常打卡-记录异常分钟数
                int betweenTime = DateUtil.getBetWeenMinutes(clockTime.substring(0, 16), compareTime);
                abnormalMinutes = abnormalMinutes + betweenTime;
            } else if (ClockPointEnum.END.equals(pointType) && ClockPointEnum.AFTER.equals(timeType)) {
                //晚退，正常打卡-记录冗余分钟数、打卡正常的时间点个数
                rightClockInNum++;
                int betweenTime = DateUtil.getBetWeenMinutes(compareTime, clockTime.substring(0, 16));
                redundantMinutes = redundantMinutes + betweenTime;
            } else if (ClockPointEnum.EQUAL.equals(timeType)) {
                //准点打卡，正常打卡-记录打卡正常的时间点个数
                rightClockInNum++;
            }

        }
        compareMap.put("judgePartA", String.valueOf(requireClockInNum));
        compareMap.put("judgePartB", String.valueOf(rightClockInNum));
        compareMap.put("judgePartC", String.valueOf(abnormalMinutes));
        compareMap.put("judgePartD", String.valueOf(redundantMinutes));
        compareMap.put("judgePartE", compareMap.get("priorityValue"));

        return compareMap;
    }

    /**
     * 获取班次要求打卡数据和请假、出差、加班数据处理后的卡点数据
     * @param empId
     * @param clockInData 需要包含分析日期以及分析日期前后2天的3天打卡数据
     * @return
     */
    private Map<String, Object> dealClockInData(String empId, Map<String, Object> pbData, List<Map<String, Object>> clockInData, String shiftId,Map<String,Map<String,Object>> clockInTimeMap) {
        Map<String, Object> clockInDataMatchInfo = new HashMap<>();
        String punchDate = Util.null2String(pbData.get("bcrq"));
        String startBeforeDate = DateUtil.beforeDay(punchDate,2);
        String endAfterDate = DateUtil.AfterDay(punchDate,2);
        //获取考勤项目
        Map<String,Object> param = Maps.newHashMap();
        param.put("startDate",startBeforeDate);
        param.put("endDate",endAfterDate);
        param.put("resourceId",empId);
        Map<String,Object> dataMap = basicsetService.getAttendanceItemsByPerson(param);

        List<Map<String,Object>> attendanceItems = (List<Map<String,Object>>)dataMap.get("data");
        //1-组装班次数据
        Map<String,List<Map<String,Object>>> schedulingResultsMap = getShiftData(empId, pbData, shiftId);

        List<Map<String,Object>> shiftData = schedulingResultsMap.get(punchDate);

        //2-拿到当天打卡数据
        Map<String, List<Map<String,Object>>> collect = Maps.newHashMap();
        if (clockInData != null && clockInData.size() >0){
            collect = clockInData.stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("signdate"))));
        }
//        Map<String,Map<String,Object>> clockInTimeMap = Maps.newHashMap(); //

        Map<String,Object> getClockTimeParam = Maps.newHashMap();
        getClockTimeParam.put("date",punchDate);
        getClockTimeParam.put("clockInTimeList",clockInData);
        getClockTimeParam.put("schedulingResultCollect",schedulingResultsMap);
        getClockTimeParam.put("clockInTimeMap",clockInTimeMap);
        getClockTimeParam.put("clockInTimeCollect",collect);
        getClockTimeParam.put("userId",empId);
        //打卡数据
        log.debug("getClockTimeParam : [{}]",getClockTimeParam);
        List<Map<String, Object>> clockInTimeList = utilService.getClockInTime(getClockTimeParam);
        //3-组装出差和请假的数据
        Map<String,Object> workingHourparam = Maps.newHashMap();
        workingHourparam.put("clockInTimeCollect",clockInTimeList);
        workingHourparam.put("analysisDate",punchDate);
        workingHourparam.put("userId",empId);
        workingHourparam.put("attendanceItems",attendanceItems);
        workingHourparam.put("scheduleResult",shiftData);
        Map<String,Object> evectionDataMap = updateAttendanceResultWrapper.getEvection(workingHourparam);
        Map<String,Object> askForLeaveDataMap = updateAttendanceResultWrapper.getAskForLeave(workingHourparam);

        //4-调用考勤分析中的卡点数据处理方法
        List<Map<String,Object>> askForLeaveAndEvctionSchedule = Lists.newArrayList();
        askForLeaveAndEvctionSchedule.addAll((List<Map<String,Object>>)askForLeaveDataMap.get("askForLeaveSchedule"));
        askForLeaveAndEvctionSchedule.addAll((List<Map<String,Object>>)evectionDataMap.get("evectionSchedule"));


        if (askForLeaveAndEvctionSchedule.size() > 0){
            askForLeaveAndEvctionSchedule = mergeAskForLeaveAndEvctionSchedule(askForLeaveAndEvctionSchedule,punchDate);
        }

        Map<String,Object> clockInTimeDataParam = Maps.newHashMap();
        clockInTimeDataParam.put("analysisDate",punchDate);
        clockInTimeDataParam.put("scheduleResult",shiftData);
        clockInTimeDataParam.put("clockInTimeList",clockInTimeList);
        clockInTimeDataParam.put("askForLeaveAndEvctionSchedule",askForLeaveAndEvctionSchedule);

        List<ClockPointDTO> clockInTimeData = utilService.getClockInPointCmd(clockInTimeDataParam);

        if(clockInTimeData != null && clockInTimeData.size() > 0) {
            clockInTimeData = clockInTimeData.stream().filter(ClockPointDTO::isRecord).collect(Collectors.toList());
        }
        clockInDataMatchInfo.put("bcId", shiftId);
        clockInDataMatchInfo.put("clockInTimeData", clockInTimeData);

        clockInDataMatchInfo.put("bcData", shiftData);
        clockInDataMatchInfo.put("bcrq", punchDate);
        return clockInDataMatchInfo;
    }

    /**
     * 获取班次数据
     * @param empId
     * @return
     */
    private Map<String,List<Map<String,Object>>> getShiftData(String empId, Map<String, Object> pbData, String shiftId) {

        String punchDate = Util.null2String(pbData.get("bcrq"));
        String schedulingRule = Util.null2String(pbData.get("pbgl"));
        String dateType = Util.null2String(pbData.get("rqlx"));
        String restSign = Util.null2String(pbData.get("sfxx"));

        String startBeforeDate = DateUtil.beforeDay(punchDate,2);
        String endAfterDate = DateUtil.AfterDay(punchDate,2);

        /** 获取人员班次*/
        Map<String,Object> classesParamMap = Maps.newHashMap();
        classesParamMap.put("tableName","uf_pbjg");
        classesParamMap.put("startDate",startBeforeDate);
        classesParamMap.put("endDate",endAfterDate);
        classesParamMap.put("pblx","0");
        classesParamMap.put("pbdx",empId);
        classesParamMap.put("current","1");
        classesParamMap.put("pageSize",10);
        classesParamMap.put("recurrence",1);

        classesParamMap.put("punchDate",punchDate);
        classesParamMap.put("schedulingRule",schedulingRule);
        classesParamMap.put("dateType",dateType);
        classesParamMap.put("restSign",restSign);
        classesParamMap.put("shiftId",shiftId);
        Map<String,List<Map<String,Object>>> schedulMap = getSchedulingInFormation(classesParamMap);

        return schedulMap;
    }

    private Map<String,List<Map<String,Object>>> getSchedulingInFormation(Map<String,Object> params) {

        String punchDate = Util.null2String(params.get("punchDate"));
        String schedulingRule = Util.null2String(params.get("schedulingRule"));
        String dateType = Util.null2String(params.get("dateType"));
        String restSign = Util.null2String(params.get("restSign"));
        String shiftId = Util.null2String(params.get("shiftId"));

        String bcSql = "select * from uf_jcl_kq_bcxx where id = " + shiftId;
        Map<String, Object> bcData = DbTools.getSqlToMap(bcSql);
        String bcsdxx = Util.null2String(bcData.get("bcsdxx"));

        String sql = "select a.xxbdkzdjb,a.sfxx,a.id bcxx,a.edsc,a.zgzsc,a.bcsdxx,a.sfdx,a.sfkt,b.bdlx,a.btgz,a.fgsjd,a.zddxfz,a.dxhs,b.kssj dtkssj,b.jssj dtjssj,b.ksdk,b.jsdk,b.tqdkfzs,b.thdkfzs,b.edxss,b.edfzs,b.edts,b.sfdx dtsfdx,b.zddxfz dtzddxfz,b.dxhs dtdxhs,b.gsrq from uf_jcl_kq_bcxx a left join uf_jcl_kq_bcxx_dt1 b on a.id=b.mainid where a.id =" + shiftId;
        List<Map<String,Object>> dataList = DbTools.getSqlToList(sql);
        Map<String,List<Map<String,Object>>> resultMap = Maps.newHashMap();
        List<Map<String,Object>> classs = Lists.newArrayList();
        for (Map<String,Object> map:dataList){
            Map<String,Object> newMap = Maps.newHashMap();
            newMap.putAll(map);
            newMap.put("rqlx",dateType);
//            newMap.put("sfxx",restSign);
            if (!newMap.get("sfxx").equals(CheckBoxEnum.CHECKED.getKey())){
                newMap.put("sfxx",restSign);
            }
            classs.add(newMap);
        }
        resultMap.put(punchDate,classs);

        /** 加班计划*/
        sql = "select a.id,b.jbry,b.ksrq,b.kssj,b.jblx,b.jsrq,b.jssj,b.jbsc,b.gsrq from uf_jcl_kq_jbjh a left join uf_jcl_kq_jbjh_dt1 b on a.id=b.mainid where b.jbry =? and b.gsrq>=? and b.gsrq<=? and (b.jbcx=0 or b.jbcx is null) and  a.jlzt=1";
        Map<String,List<Map<String,Object>>> overtimePlanMap = DbTools.getSqlToList(sql,params.get("pbdx"),punchDate,punchDate).stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("gsrq"))));

        //考勤项目
        List<Map<String,Object>> attendanceItems = new ArrayList<>();
        //日期集合
//        Map<String,Object> dateParam = Maps.newHashMap();
//        dateParam.put("nd",Util.null2String(params.get("startDate")).split("-")[0]);
//        dateParam.put("glpb",schedulingRule);
//        Map<String,Object> result = commandExecutor.execute(new GetDateCmd(dateParam));
//        List<Map<String,Object>> list = (List<Map<String,Object>>)result.get("data");
//        Map<String,String> dateMap = list.stream().collect(Collectors.toMap(e->Util.null2String(e.get("rq")),e->Util.null2String(e.get("rqlx"))));


        for (Map.Entry<String,List<Map<String,Object>>> e: overtimePlanMap.entrySet()){
            if (resultMap.get(e.getKey()) == null){
                resultMap.put(e.getKey(),Lists.newArrayList());
            }
            List<Map<String,Object>> resultList = resultMap.get(e.getKey());
//            List<Map<String,Object>> schedulingdateMap = schedulingMapBydate.get(e.getKey());
            List<Map<String,Object>> overtimePlanList = e.getValue();
            for (Map<String,Object> overtimePlan:overtimePlanList){
                Map<String,Object> map = Maps.newHashMap();
                if (!overtimePlan.get("ksrq").equals(overtimePlan.get("jsrq"))){
                    map.put("sfkt","1");
                }else {
                    map.put("sfkt","0");
                }
                //查找对应的考勤项目
                String querySql = "select a.id keyid,a.* from uf_jcl_kq_kqxm a where id=?";
                attendanceItems = DbTools.getSqlToList(querySql,overtimePlan.get("jblx"));


                map.put("bcxx", punchDate.compareTo(e.getKey()) != 0 ? "0" : shiftId);
                map.put("bcsdxx", punchDate.compareTo(e.getKey()) != 0  ? "": bcsdxx);
                if (resultList.size()>0){
                    map.putAll(resultList.get(0));
//                map.put("edsc",Util.null2String(resultList.get(0).get("edsc")));
//                map.put("sfdx",Util.null2String(resultList.get(0).get("sfdx")));
//                map.put("zddxfz",Util.null2String(resultList.get(0).get("zddxfz")));
//                map.put("dxhs",Util.null2String(resultList.get(0).get("dxhs")));
//                map.put("sfxx",resultList.get(0).get("sfxx"));
//                map.put("btgz",resultList.get(0).get("btgz"));
//                map.put("xxbdkzdjb",resultList.get(0).get("xxbdkzdjb"));
                }else {
                    map.put("edsc","0");
                }
                map.put("edts","0");
                map.put("bdlx", ClassSegmentTypeEnum.OVERTIME_PLAN.getKey());
                map.put("dtkssj",overtimePlan.get("kssj"));
                map.put("dtjssj",overtimePlan.get("jssj"));
                map.put("ksdk","0");
                map.put("jsdk","0");
                map.put("overtimePlanId",overtimePlan.get("id"));
                if (punchDate.compareTo(e.getKey()) == 0){
                    map.put("sfxx", restSign);
                }
                map.put("tqdkfzs", ExtensionClassHolder.getGlobalSetMap().get("defaultClockRange") == null?"60":ExtensionClassHolder.getGlobalSetMap().get("defaultClockRange"));
                map.put("thdkfzs",ExtensionClassHolder.getGlobalSetMap().get("defaultClockRange") == null?"60":ExtensionClassHolder.getGlobalSetMap().get("defaultClockRange"));
                map.put("rqlx",dateType);
                map.put("edxss",overtimePlan.get("jbsc"));
                map.put("edfzs",Double.valueOf(overtimePlan.get("jbsc").toString())*60);
                map.put("jblx",attendanceItems);
                if (DateUtil.getTime(overtimePlan.get("ksrq").toString()).compareTo(DateUtil.getTime(e.getKey())) < 0){
                    map.put("gsrq", ClassBelongToEnum.YESTERDAY.getKey());
                }else if (DateUtil.getTime(overtimePlan.get("ksrq").toString()).compareTo(DateUtil.getTime(e.getKey())) == 0){
                    map.put("gsrq", ClassBelongToEnum.NOWDAY.getKey());
                }else if (DateUtil.getTime(overtimePlan.get("ksrq").toString()).compareTo(DateUtil.getTime(e.getKey())) > 0){
                    map.put("gsrq", ClassBelongToEnum.NEXTDAY.getKey());
                }
                if (attendanceItems.size() >0){
                    map.put("ksdk",attendanceItems.get(0).get("ksjbbxydk"));
                    map.put("jsdk",attendanceItems.get(0).get("jsjbbxydk"));
                    map.put("tqdkfzs",attendanceItems.get(0).get("tqdkyxfzs"));
                    map.put("thdkfzs",attendanceItems.get(0).get("thdkyxfzs"));
                    map.put("jbwdhlfzs",attendanceItems.get(0).get("jbwdhlfzs"));
                    map.put("jbzzhlfzs",attendanceItems.get(0).get("jbzzhlfzs"));
                }
                if (resultList.size() > 0){
                    String kssjbegin = Utils.getkssjTime(resultList.get(0),e.getKey());
                    String kssjend = Utils.getkssjTime(resultList.get(resultList.size()-1),e.getKey());
                    String kssj = overtimePlan.get("ksrq")+" "+overtimePlan.get("kssj");
                    if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(kssjbegin)) <0){
                        //加班计划在开头
                        resultList.add(0,map);
                    }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(kssjend)) >0){
                        //加班计划在末尾
                        resultList.add(map);
                    }else {
                        if (resultList.size() > 1){
                            //加班计划在中间
                            for (int j=1;j<resultList.size();j++){
                                String kssj1 = Utils.getkssjTime(resultList.get(j),e.getKey());
                                String kssj2 = overtimePlan.get("ksrq")+" "+overtimePlan.get("kssj");
                                String kssj3 = Utils.getkssjTime(resultList.get(j-1),e.getKey());
                                if (DateUtil.getTime(kssj1).compareTo(DateUtil.getTime(kssj2)) >=0 &&  DateUtil.getTime(kssj3).compareTo(DateUtil.getTime(kssj2)) <=0){
                                    resultList.add(j,map);
                                    break;
                                }
                            }
                        }
                    }
                }else {
                    resultList.add(map);
                }
            }
        }
        log.debug("SchedulingResults : [{}]",resultMap);
        return resultMap;
    }

    /**
     * 合并请假或出差
     *
     * @param askForLeaveAndEvctionSchedule
     * @param analysisDate
     * @return
     */
    public List<Map<String, Object>> mergeAskForLeaveAndEvctionSchedule(List<Map<String, Object>> askForLeaveAndEvctionSchedule, String analysisDate) {

        askForLeaveAndEvctionSchedule = askForLeaveAndEvctionSchedule.stream().sorted(Comparator.comparing(e -> DateUtil.getTime(Utils.getkssjTime(e, analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());

        for (int i = 0; i < askForLeaveAndEvctionSchedule.size() - 1; i++) {
            String beforeDtkssj = Utils.getkssjTime(askForLeaveAndEvctionSchedule.get(i),analysisDate);
            String beforeDtjssj = Utils.getjssjTime(askForLeaveAndEvctionSchedule.get(i),analysisDate);

            for (int j = i + 1; j < askForLeaveAndEvctionSchedule.size(); j++) {
                String dtkssj = Utils.getkssjTime(askForLeaveAndEvctionSchedule.get(j),analysisDate);
                String dtjssj = Utils.getjssjTime(askForLeaveAndEvctionSchedule.get(j),analysisDate);
                if (DateUtil.getTime(beforeDtjssj).compareTo(DateUtil.getTime(dtkssj)) == 0) {
                    askForLeaveAndEvctionSchedule.get(i).put("dtjssj", dtjssj);
                    askForLeaveAndEvctionSchedule.get(i).put("jsdk", askForLeaveAndEvctionSchedule.get(j).get("jsdk"));
                    askForLeaveAndEvctionSchedule.get(i).put("thfghlfzs", askForLeaveAndEvctionSchedule.get(j).get("thfghlfzs"));
                    askForLeaveAndEvctionSchedule.remove(askForLeaveAndEvctionSchedule.get(j));
                    j--;
                    i--;
                }
            }
        }

        return askForLeaveAndEvctionSchedule;
    }
}
